package iotwisp.school.user.service;

import iotwisp.base.cqrs.BusinessException;
import iotwisp.base.cqrs.unitofwork.UseUnitOfWork;
import iotwisp.base.orm.BaseDao;
import iotwisp.base.util.PwdUtil;
import iotwisp.school.system.entity.Image;
import iotwisp.school.system.service.ImageService;
import iotwisp.school.user.command.admin.*;
import iotwisp.school.user.command.login_token.CreateLoginTokenDCmd;
import iotwisp.school.user.entity.Admin;
import iotwisp.school.user.entity.LoginToken;
import iotwisp.school.user.entity.Role;
import iotwisp.school.user.exception.OrgException;
import iotwisp.school.user.qo.AdminQO;
import iotwisp.school.user.qo.RoleQO;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
@Transactional
public class AdminService extends BaseDao<Admin, AdminQO> {

    @Autowired
    private RoleService roleService;
    @Autowired
    private LoginTokenService loginTokenService;
    @Autowired
    private ImageService imageService;

    @UseUnitOfWork(description = "新增用户", operateType = UseUnitOfWork.OperateType.CREATE)
    public Admin createAdmin(CreateAdminSCmd cmd) {

        // 查出要添加的角色
        RoleQO roleQO = new RoleQO();
        roleQO.setIds(cmd.getAddRoleIds());
        List<Role> roles = roleService.queryList(roleQO);

        Set<Role> roleSet = new HashSet<>();
        for (Role role : roles) {
            roleSet.add(role);
        }

        Image image = null;
        if (StringUtils.isNotBlank(cmd.getHeadImageId())) {
            image = imageService.get(cmd.getHeadImageId());
        }

        // 新建用户
        Admin admin = new Admin();
        admin.create(cmd, roleSet, image);

        // 保存用户
        save(admin);

        return admin;
    }

    @UseUnitOfWork(description = "修改用户", operateType = UseUnitOfWork.OperateType.UPDATE)
    public Admin modifyAdmin(ModifyAdminSCmd cmd) {

        // 查出要修改的用户
        AdminQO adminQO = new AdminQO();
        adminQO.setId(cmd.getAdminId());
        adminQO.setFetchRoles(true);
        Admin admin = queryUnique(adminQO);

        Image image = null;
        if (StringUtils.isNotBlank(cmd.getHeadImageId())) {
            image = imageService.get(cmd.getHeadImageId());
        }

        // 修改用户
        admin.modify(cmd, image);

        // 要添加的角色
        if (cmd.getAddRoleIds() != null && cmd.getAddRoleIds().size() > 0) {
            RoleQO addRoleQO = new RoleQO();
            addRoleQO.setIds(cmd.getAddRoleIds());
            List<Role> addRoles = roleService.queryList(addRoleQO);
            for (Role role : addRoles) {
                admin.getRoleSet().add(role);
            }
        }

        // 要移除的角色
        if (cmd.getRemoveRoleIds() != null && cmd.getRemoveRoleIds().size() > 0) {
            RoleQO removeRoleQO = new RoleQO();
            removeRoleQO.setIds(cmd.getRemoveRoleIds());
            List<Role> removeRoles = roleService.queryList(removeRoleQO);

            for (Role role : removeRoles) {
                admin.getRoleSet().remove(role);
            }
        }

        update(admin);

        return admin;
    }

    @UseUnitOfWork(description = "修改用户状态", operateType = UseUnitOfWork.OperateType.UPDATE)
    public void changeAdminEnable(ChangeAdminEnableSCmd cmd) {

        // 查出用户
        Admin admin = get(cmd.getAdminId());
        // 修改启用状态
        admin.changeEnable(cmd);

        update(admin);
    }

    public LoginToken adminLogin(AdminLoginSCmd cmd) throws BusinessException {

        // 根据登录名查出用户
        AdminQO adminQO = new AdminQO();
        adminQO.setLoginName(cmd.getLoginName());
        adminQO.setEnable(true);
        Admin admin = queryUnique(adminQO);
        // 不存在抛异常
        if (admin == null) {
            throw BusinessException.getInstance(OrgException.USER_NOT_FOUND, "用户不存在");
        }
        // 校验密码是否匹配，不匹配抛异常
        if (!StringUtils.equals(admin.getPassword(), PwdUtil.getPwd(cmd.getPassword()))) {
            throw BusinessException.getInstance(OrgException.PASSWORD_WRONG, "用户名或密码错误");
        }

        if (cmd.getHeader() == null) {
            throw BusinessException.getInstance(BusinessException.NECESSARY_PARAM_NULL, "指令头缺少客户端信息");
        }
        // 创建登录令牌
        CreateLoginTokenDCmd createLoginTokenDCmd = new CreateLoginTokenDCmd();
        createLoginTokenDCmd.setClientId(cmd.getHeader().getClientId());
        createLoginTokenDCmd.setClientType(cmd.getHeader().getClientType());

        Calendar expireCalendar = Calendar.getInstance();
        expireCalendar.add(Calendar.DATE, 1);
        createLoginTokenDCmd.setExpireDate(expireCalendar.getTime());

        createLoginTokenDCmd.setLoginName(cmd.getLoginName());
        createLoginTokenDCmd.setIp(cmd.getHeader().getClientIp());
        createLoginTokenDCmd.setSubjectId(admin.getId());
        LoginToken loginToken = loginTokenService.createLoginTokdn(createLoginTokenDCmd);

        return loginToken;
    }

    public void adminLogout(AdminLogoutSCmd cmd) {

        // 根据用户id和客户端id查出有效令牌

        // 删除令牌

    }

    @Override
    protected Criteria buildCriteria(Criteria criteria, AdminQO qo) {
        return criteria;
    }

    @Override
    protected Class<Admin> getEntityClass() {
        return Admin.class;
    }

}
